package com.nineclock.system.service.impl;

import com.nineclock.common.aliyun.sms.SmsUtils;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.CheckCodeException;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.redis.CacheService;
import com.nineclock.common.utils.CurrentUserHolder;
import com.nineclock.system.service.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;

/**
 * @author yangchao
 * @create 2022-01-14 10:06
 **/
@Transactional
@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private CacheService cacheService;

    /**
     * 生成前缀
     * @param type
     * @return
     */
    private String getKeyPrefix(String type) {
        //设置key前缀
        String keyPrefix = "";

        //判断登录类型
        switch (type){
            case SMSConstant.SMS_TYPE_LOGIN:
                keyPrefix = SMSConstant.SMS_LOGIN_KEY_PREFIX;
                break;
            case SMSConstant.SMS_TYPE_REGISTER:
                keyPrefix = SMSConstant.SMS_REGISTER_KEY_PREFIX;
                break;
            case SMSConstant.SMS_TYPE_CHANGE_MANAGER:
                keyPrefix = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX;
                break;
            case SMSConstant.SMS_TYPE_RESET_PASSWORD:
                keyPrefix = SMSConstant.SMS_RESET_KEY_PREFIX;
                break;
        }
        return keyPrefix;
    }

    /**
     * 发送短信验证码
     * @param mobile 发送的电话
     * @param type
     * | 1    | 登录         |
     * | 2    | 注册         |
     * | 3    | 更换主管理员 |
     * | 4    | 重置密码     |
     */
    @Override
    public void sendSMSMessage(String mobile, String type) {

        //校验参数是否合法
        if(mobile == null || mobile.length() == 0 || Integer.parseInt(type) > 4 || Integer.parseInt(type) <= 0){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //如果要更换主管理员，重置密码，需要进行用户检验
        if(type.equals("3") || type.equals("4")){
            //判断用户是否登录
            if(CurrentUserHolder.get() == null){
                throw new NcException(ResponseEnum.UNAUTHORIZED);
            }
        }

        String keyPrefix = getKeyPrefix(type);

        //发送验证码
        sendSMSMessageUtils(mobile,keyPrefix);

    }

    /**
     * 发送验证码-工具方法
     * @param mobile
     */
    private void sendSMSMessageUtils(String mobile,String key_prefix) {

        //生成随机验证码
        String checkCode = smsUtils.generateCheckCode();

        //发送短信
//        smsUtils.sendSms(mobile,checkCode);
        log.info("发送短信[手机号：{},验证码：{}]",mobile,checkCode);

        //将信息发送给redis(存在redis中，设置5分钟有效)
        String key = key_prefix + mobile;
        cacheService.setEx(key,checkCode,5, TimeUnit.MINUTES);

    }

    /**
     * 验证码校验
     * @param checkCode 验证码
     * @param mobile 手机号
     * @param type 验证码类型
     * @return
     */
    @Override
    public void verifySMSMessage(String checkCode, String mobile, String type) {

        //校验参数是否合法
        if(checkCode == null || checkCode.length() == 0 ||mobile == null || mobile.length() == 0 || Integer.parseInt(type) > 4 || Integer.parseInt(type) <= 0){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //如果要更换主管理员，重置密码，需要进行用户检验
        if(type.equals("3") || type.equals("4")){
            //判断用户是否登录
            if(CurrentUserHolder.get() == null){
                throw new NcException(ResponseEnum.UNAUTHORIZED);
            }
        }

        String key = getKeyPrefix(type) + mobile;
        //获取Redis中的验证码
        String codeFromRedis = cacheService.get(key);

        //验证码过期或者不存在
        if(codeFromRedis == null){
//            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE,"验证码已过期，请重新发送验证码！");
            throw new CheckCodeException(ResponseEnum.EXPIRE_VERIFY_CODE,"验证码已过期，请重新发送验证码！");
        }

        //判断验证码是否正确
        if(!checkCode.equals(codeFromRedis)){
//            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
            throw new CheckCodeException(ResponseEnum.INVALID_VERIFY_CODE,"验证码错误，请重新输入！");
        }

    }

}
